package com.yeskery.nut.web.demo.interceptor;

import com.yeskery.nut.annotation.bean.Component;
import com.yeskery.nut.annotation.environment.Value;
import com.yeskery.nut.core.Cookie;
import com.yeskery.nut.core.RequestApplicationContext;
import com.yeskery.nut.extend.auth.AuthPlugin;
import com.yeskery.nut.extend.i18n.MessageService;
import com.yeskery.nut.util.ControllerUtils;
import com.yeskery.nut.util.StringUtils;
import com.yeskery.nut.web.demo.common.Auth;
import com.yeskery.nut.web.demo.common.Constants;
import com.yeskery.nut.web.demo.common.R;
import com.yeskery.nut.web.demo.common.UserContext;
import com.yeskery.nut.web.demo.exception.AuthException;

import javax.annotation.PostConstruct;
import java.util.Arrays;
import java.util.Set;

/**
 * 登录认证拦截器
 * @author Yeskery
 * 2023/7/28
 */
@Component
public class AuthInterceptor extends AuthPlugin {

    @Value("${server.unauth.uris}")
    private Set<String> unAuthUris;

    public AuthInterceptor(MessageService messageService) {
        super((request, controller) -> {
            String token = request.getHeader(Constants.AUTH_TOKEN_REQUEST_HEADER_KEY);
            if (StringUtils.isEmpty(token)) {
                token = request.getParameter(Constants.AUTH_TOKEN_REQUEST_HEADER_KEY);
            }
            if (StringUtils.isEmpty(token)) {
                token = Arrays.stream(request.getCookies())
                        .filter(c -> c.getName().equals(Constants.AUTH_TOKEN_REQUEST_HEADER_KEY))
                        .map(Cookie::getValue)
                        .findFirst()
                        .orElse(null);
            }
            if (StringUtils.isEmpty(token)) {
                return false;
            }
            RequestApplicationContext.putResource(Constants.AUTH_TOKEN_KEY, token);
            Auth auth = ControllerUtils.getAnnotationControllerMethodOrClassAnnotation(controller, request, Auth.class);
            boolean required = auth == null || auth.required();
            if (required) {
                try {
                    return UserContext.getUser() != null;
                } catch (AuthException e) {
                    return false;
                }
            }
            return true;
        }, (request, response, execution) -> response.writeJsonFromObject(R.fail(messageService.getMessage("token.invalid"))));
    }

    @PostConstruct
    public void init() {
        unAuthUris.forEach(this::addNoAuthPath);
    }
}
